import {
    Alert,
    Button,
    Input,
    Link,
    Message,
    Radio,
    Select,
    Switch,
    Tabs,
    Typography,
} from '@arco-design/web-react'
import { IconDelete } from '@arco-design/web-react/icon'
import React from 'react'
import {
    IApiHandler,
    IApiHandlerIds,
    IApiItem,
    IExpectItem,
    IMethod,
} from '../../../../utils/interfaces'
import { randomStr } from '../../../../utils/random'
import { apiStore } from '../../../../utils/store/apiStore'
import ContextMenu from '../../components/ContextMenu'
import MethodTag from '../../components/MethodTag'
import ApiHandlerEdit from './ApiHandlerEdit'
import HandlerReadme from './HandlerReadme'
import Variables from './Variables'

const { Title } = Typography
const RadioGroup = Radio.Group

interface IEditApiProps {
    apiItem: IApiItem
    // 数据更新后
    onUpdated?: () => void
}

const methods: IMethod[] = [
    '',
    'GET',
    'POST',
    'PUT',
    'DELETE',
    'PATCH',
    'HEAD',
    'OPTIONS',
]

const apiHandlers: {
    id: IApiHandlerIds
    label: string
}[] = [
    { id: 'reqHeaders', label: '请求头' },
    { id: 'reqBody', label: '请求体' },
    { id: 'resHeaders', label: '响应头' },
    { id: 'resBody', label: '响应体' },
]

const EditApi: React.FC<IEditApiProps> = ({
    apiItem: propsApiItem,
    onUpdated,
}) => {
    // 数据
    const [values, setValues] = useState(propsApiItem)
    // 使用ref保存数据，避免 使用闭包拿到旧快照 问题
    const valuesRef = useRef(propsApiItem)
    // 正在添加的期望名称
    const [expectName, setExpectName] = useState<string | undefined>()
    // 请求处理tab
    const [bodyActiveTab, setBodyActiveTab] =
        useState<IApiHandlerIds>('resBody')

    // 点击保存
    const handleSave = async () => {
        // 空值检查
        if (
            !['variables', 'handlers', 'expects', 'label', 'url'].some(
                (k) => !!values[k as keyof IApiItem],
            )
        ) {
            Message.warning('内容为空')
            return
        }
        // url必填
        if (!values.url) {
            Message.warning('请填写请求地址')
            return
        }
        // 保存数据
        await apiStore.save(values)
        // 更新列表
        onUpdated?.()
        Message.success('保存成功')
    }

    // 表单数据变化
    const handleChange = <K extends keyof IApiItem>(
        key: K,
        value: IApiItem[K],
    ) => {
        setValues((prev) => {
            const cloned = { ...prev }
            cloned[key] = value
            valuesRef.current = cloned

            return cloned
        })
    }

    // 添加期望
    const handleAddExpect = () => {
        const values = valuesRef.current
        if (expectName === undefined) {
            setExpectName('')
            return
        }
        // 空值检查
        const trimed = expectName.trim()
        if (!trimed) {
            setExpectName(undefined)
            return
        }
        // 添加
        const newExpect: IExpectItem = {
            id: randomStr(),
            label: trimed,
            type: 'expect',
        }
        const oldExpects = values.expects || []
        handleChange('expects', [...oldExpects, newExpect])
        setExpectName(undefined)
    }

    // 是默认期望吗
    const isDefaultExpect = () => {
        const values = valuesRef.current
        return !values.expectId || values.expectId === 'default'
    }

    // 变量配置变化
    const handleVariablesChange = (variables: IApiItem['variables']) => {
        const values = valuesRef.current
        // 如果当前选中的是默认期望，则修改变量配置
        if (isDefaultExpect()) {
            handleChange('variables', variables)
            return
        }
        // 修改期望
        const newExpects = values.expects?.map((item) =>
            item.id === values.expectId ? { ...item, variables } : item,
        )
        handleChange('expects', newExpects)
    }

    // 请求处理发生变化
    const handleHandlersChange = <K extends keyof IApiHandler>(
        id: IApiHandlerIds,
        key: K,
        value: IApiHandler[K],
    ) => {
        const newValues = valuesRef.current
        // 如果是默认期望直接更改
        if (isDefaultExpect()) {
            handleChange('handlers', {
                ...newValues.handlers,
                [id]: {
                    ...newValues.handlers?.[id],
                    [key]: value,
                },
            })
            return
        }
        const newExpects = newValues.expects?.map((item) =>
            item.id === newValues.expectId
                ? {
                      ...item,
                      handlers: {
                          ...item.handlers,
                          [id]: {
                              ...item.handlers?.[id],
                              [key]: value,
                          },
                      },
                  }
                : item,
        )
        handleChange('expects', newExpects)
    }

    // 获取当前选中期望的变量配置
    const getCurrentExpectData = () => {
        const values = valuesRef.current
        if (isDefaultExpect()) {
            return { variables: values.variables, handlers: values.handlers }
        }
        const expect = values.expects?.find(
            (item) => item.id === values.expectId,
        )
        return {
            variables: expect?.variables,
            handlers: expect?.handlers,
        }
    }

    // 删除期望
    const handleDeleteExpect = (expect: IExpectItem) => {
        const newExpects = values.expects?.filter(
            (item) => item.id !== expect.id,
        )
        handleChange('expects', newExpects)
        handleChange('expectId', 'default')
    }

    // 添加变量
    const handleAddVariable = (name?: string, type?: IVariableType) => {
        const newValues = valuesRef.current
        // 切换到默认期望
        handleChange('expectId', 'default')
        handleVariablesChange([
            ...(newValues.variables || []),
            {
                id: randomStr(),
                name: name || `var_${randomStr(4)}`,
                type: type || 'string',
            },
        ])
    }

    return (
        <div>
            {/* 是否启用，保存 */}
            <div className='!mt-0 !mb-4 flex justify-between items-center'>
                <div>
                    是否启用：
                    <Switch
                        checked={values.enabled}
                        onChange={(v) => handleChange('enabled', v)}
                        className='mr-2'
                    />
                </div>
                <Button type='primary' onClick={handleSave}>
                    保存
                </Button>
            </div>
            {/* 名称 */}
            <div className='flex mb-4 items-center'>
                <Input
                    className='flex-1'
                    allowClear
                    placeholder='请输入名称'
                    size='large'
                    value={values.label}
                    onChange={(v) => handleChange('label', v)}
                />
            </div>
            {/* 请求方法，匹配模式，请求地址 */}
            <div className='flex'>
                {/* 请求方法 */}
                <Select
                    className='mr-2'
                    placeholder='请求方法'
                    defaultValue=''
                    style={{ width: 120 }}
                    options={methods.map((value) => ({
                        label: <MethodTag size='large' method={value} />,
                        value,
                    }))}
                    size='large'
                    value={values.method}
                    onChange={(v) => handleChange('method', v)}
                ></Select>
                {/* 匹配方法 及 地址 */}
                <Input
                    addBefore={
                        <Select
                            placeholder='匹配模式'
                            style={{ width: 100 }}
                            defaultValue='includes'
                            options={[
                                { label: '包含', value: 'includes' },
                                { label: '相等', value: 'equal' },
                                { label: '正则', value: 'regExp' },
                            ]}
                            value={values.machMode || 'includes'}
                            onChange={(v) => handleChange('machMode', v)}
                        ></Select>
                    }
                    className='flex-1'
                    allowClear
                    placeholder='输入地址'
                    size='large'
                    value={values.url}
                    onChange={(v) => handleChange('url', v)}
                />
            </div>
            {/* 预设 */}
            <Title heading={6}>期望</Title>
            <div className='flex'>
                <RadioGroup
                    className='shrink-0'
                    type='button'
                    name='lang'
                    size='large'
                    defaultValue='default'
                    value={values.expectId || 'default'}
                    onChange={(v) => handleChange('expectId', v)}
                >
                    <Radio value='default'>默认</Radio>
                    {values.expects?.map((item) => (
                        <ContextMenu
                            items={[
                                {
                                    label: (
                                        <>
                                            <IconDelete className='!text-red-500' />
                                            删除
                                        </>
                                    ),
                                    onClick: () => handleDeleteExpect(item),
                                },
                            ]}
                        >
                            <Radio key={item.id} value={item.id}>
                                {item.label}
                            </Radio>
                        </ContextMenu>
                    ))}
                </RadioGroup>
                <div className='flex ml-2'>
                    {expectName !== undefined && (
                        <Input
                            value={expectName}
                            autoFocus
                            onChange={setExpectName}
                        />
                    )}
                    <Button
                        className='ml-2'
                        size='large'
                        type={expectName !== undefined ? 'primary' : 'default'}
                        onClick={handleAddExpect}
                    >
                        {expectName !== undefined ? '确定' : '添加'}
                    </Button>
                </div>
            </div>
            {/* 变量 */}
            <Title heading={6}>
                变量
                <Button
                    className='ml-2'
                    size='small'
                    disabled={!isDefaultExpect()}
                    onClick={() => handleAddVariable()}
                >
                    添加
                </Button>
            </Title>
            <Variables
                updateKey={values.expectId || 'default'}
                isDefault={isDefaultExpect()}
                defaultExpectVariables={values.variables}
                value={getCurrentExpectData().variables}
                onChange={handleVariablesChange}
            />
            {/* 请求处理 */}
            <Title className='group' heading={6}>
                请求处理
                <HandlerReadme />
                <Link
                    className='ml-2 hidden group-hover:inline'
                    href='http://mockjs.com/examples.html'
                    target='_blank'
                >
                    {' '}
                    MockJs示例{' '}
                </Link>
            </Title>
            <Tabs
                className='my-2'
                type='rounded'
                activeTab={bodyActiveTab}
                onChange={(k) => setBodyActiveTab(k as IApiHandlerIds)}
            >
                {apiHandlers.map((item) => {
                    return (
                        <Tabs.TabPane
                            key={item.id}
                            title={
                                <div>
                                    {item.label}
                                    <Switch
                                        size='small'
                                        checked={
                                            getCurrentExpectData().handlers?.[
                                                item.id
                                            ]?.enabled
                                        }
                                        onChange={(v) =>
                                            handleHandlersChange(
                                                item.id,
                                                'enabled',
                                                v,
                                            )
                                        }
                                        className='ml-2'
                                    />
                                </div>
                            }
                        ></Tabs.TabPane>
                    )
                })}
            </Tabs>
            {/* 内容编辑 */}
            {bodyActiveTab !== 'resBody' && (
                <Alert
                    className='my-2'
                    type='error'
                    content='目前仅支持修改响应体，其他功能正在开发中'
                />
            )}
            <ApiHandlerEdit
                updateKey={bodyActiveTab + (values.expectId || 'default')}
                value={
                    getCurrentExpectData().handlers?.[bodyActiveTab]?.mockRule
                }
                onChange={(v) =>
                    handleHandlersChange(bodyActiveTab, 'mockRule', v)
                }
                onAddVariable={handleAddVariable}
                apiItem={values}
            />
            {/* <Editor /> */}
        </div>
    )
}

export default EditApi
